package edu.ynu.se.xiecheng.achitectureclass.service;

import edu.ynu.se.xiecheng.achitectureclass.dao.CameraDataRepository;
import edu.ynu.se.xiecheng.achitectureclass.dao.DeviceRepository;
import edu.ynu.se.xiecheng.achitectureclass.dao.SoilDataRepository;
import edu.ynu.se.xiecheng.achitectureclass.entity.Device;
import edu.ynu.se.xiecheng.achitectureclass.entity.SoilData;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据分析服务
 * 负责处理和分析从设备采集的数据，生成统计信息和趋势分析
 */
@Service
@RequiredArgsConstructor
public class DataAnalysisService {
    private final SoilDataRepository soilDataRepository;
    private final CameraDataRepository cameraDataRepository;
    private final DeviceRepository deviceRepository;

    /**
     * 设备数据摘要
     * 包含单个设备的数据统计信息
     */
    @Data
    public static class DeviceDataSummary {
        private String deviceName;      // 设备名称
        private String deviceType;      // 设备类型
        private String unit;            // 测量单位
        private Double minValue;        // 最小值
        private Double maxValue;        // 最大值
        private Double avgValue;        // 平均值
        private LocalDateTime lastUpdateTime;  // 最后更新时间
    }

    /**
     * 大棚数据摘要
     * 包含整个大棚的设备和数据统计信息
     */
    @Data
    public static class GreenhouseDataSummary {
        private Long greenhouseId;      // 大棚ID
        private String greenhouseName;  // 大棚名称
        private List<DeviceDataSummary> deviceSummaries;  // 设备数据摘要列表
        private int totalDevices;       // 设备总数
        private int activeDevices;      // 活跃设备数
        private LocalDateTime lastUpdateTime;  // 最后更新时间
    }

    /**
     * 将Date转换为LocalDateTime
     */
    private LocalDateTime convertToLocalDateTime(Date date) {
        if (date == null) return null;
        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
    }

    /**
     * 将LocalDateTime转换为Date
     */
    private Date convertToDate(LocalDateTime dateTime) {
        if (dateTime == null) return null;
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取土壤设备的数据摘要
     */
    private DeviceDataSummary getSoilDeviceDataSummary(Device device) {
        List<SoilData> dataList = soilDataRepository.findByDeviceOrderByCreateTimeDesc(device);
        if (dataList.isEmpty()) {
            return null;
        }

        DeviceDataSummary summary = new DeviceDataSummary();
        summary.setDeviceName(device.getName());
        summary.setDeviceType(device.getDeviceType());
        summary.setUnit(device.getUnit());

        DoubleSummaryStatistics stats = dataList.stream()
                .mapToDouble(SoilData::getValue)
                .summaryStatistics();

        summary.setMinValue(stats.getMin());
        summary.setMaxValue(stats.getMax());
        summary.setAvgValue(stats.getAverage());
        summary.setLastUpdateTime(convertToLocalDateTime(dataList.get(0).getCreateTime()));

        return summary;
    }

    /**
     * 获取大棚数据摘要
     */
    public GreenhouseDataSummary getGreenhouseDataSummary(Long greenhouseId) {
        List<Device> devices = deviceRepository.findByGreenhouseId(greenhouseId);
        if (devices.isEmpty()) {
            return null;
        }

        GreenhouseDataSummary summary = new GreenhouseDataSummary();
        summary.setGreenhouseId(greenhouseId);
        summary.setTotalDevices(devices.size());

        List<DeviceDataSummary> deviceSummaries = new ArrayList<>();
        int activeCount = 0;
        LocalDateTime lastUpdate = null;

        for (Device device : devices) {
            if (!device.getDeviceType().equals("camera")) {
                DeviceDataSummary deviceSummary = getSoilDeviceDataSummary(device);
                if (deviceSummary != null) {
                    deviceSummaries.add(deviceSummary);
                    if (deviceSummary.getLastUpdateTime() != null) {
                        if (lastUpdate == null || deviceSummary.getLastUpdateTime().isAfter(lastUpdate)) {
                            lastUpdate = deviceSummary.getLastUpdateTime();
                        }
                        activeCount++;
                    }
                }
            }
        }

        summary.setDeviceSummaries(deviceSummaries);
        summary.setActiveDevices(activeCount);
        summary.setLastUpdateTime(lastUpdate);

        return summary;
    }

    /**
     * 获取设备在线状态
     */
    public Map<String, String> getDeviceStatus(Long greenhouseId) {
        List<Device> devices = deviceRepository.findByGreenhouseId(greenhouseId);
        Map<String, String> statusMap = new HashMap<>();
        LocalDateTime threshold = LocalDateTime.now().minusMinutes(10);

        for (Device device : devices) {
            if (!device.getDeviceType().equals("camera")) {
                Optional<SoilData> lastData = soilDataRepository.findFirstByDeviceOrderByCreateTimeDesc(device);
                String status = lastData
                        .map(data -> convertToLocalDateTime(data.getCreateTime()).isAfter(threshold) ? "在线" : "离线")
                        .orElse("未知");
                statusMap.put(device.getName(), status);
            } else {
                boolean hasRecentCapture = cameraDataRepository.existsByDeviceAndCreateTimeAfter(device, convertToDate(threshold));
                statusMap.put(device.getName(), hasRecentCapture ? "在线" : "离线");
            }
        }

        return statusMap;
    }

    /**
     * 获取指定时间范围内的数据趋势
     */
    public Map<String, List<Map<String, Object>>> getDataTrend(Long greenhouseId, LocalDateTime startTime, LocalDateTime endTime) {
        List<Device> devices = deviceRepository.findByGreenhouseId(greenhouseId);
        Map<String, List<Map<String, Object>>> trends = new HashMap<>();

        for (Device device : devices) {
            if (!device.getDeviceType().equals("camera")) {
                List<SoilData> dataList = soilDataRepository.findByDeviceAndCreateTimeBetweenOrderByCreateTimeAsc(
                        device, convertToDate(startTime), convertToDate(endTime));

                List<Map<String, Object>> deviceData = dataList.stream()
                        .map(data -> {
                            Map<String, Object> point = new HashMap<>();
                            point.put("time", convertToLocalDateTime(data.getCreateTime()));
                            point.put("value", data.getValue());
                            return point;
                        })
                        .collect(Collectors.toList());

                trends.put(device.getName(), deviceData);
            }
        }

        return trends;
    }
} 